import { message } from 'ant-design-vue';
import Color from 'color';
import * as echarts from 'echarts';
import { isEmpty } from 'lodash-es';

interface Data {
  [key: string]: [[number, number]];
}
interface Grid {
  show: boolean;
  top?: string;
  left?: string;
  width?: string;
  height?: string;
  containLabel: boolean;
}

interface Legend {
  data: string[];
  selectedMode?: 'multiple' | 'single' | 'none';
  show?: boolean;
  left?: string;
  top?: string;
  textStyle?: Record<string, any>;
}

interface Channels {
  label?: string;
  name: string;
  color: string;
  grid?: Grid;
  yName?: string;
}

interface Opt {
  target: HTMLElement;
  channels: Channels[];
  direction?: 'horizontal' | 'vertical';
  title: string | false;
  once?: boolean;
  legend?: Legend[] | Legend;
}

interface Series {
  type: 'line';
  name: string;
  showSymbol: boolean;
  data: [number, number][];
  xAxisId: number;
  yAxisId: number;
  lineStyle?: Record<string, any>;
  encode?: {
    x: number;
    y: number; // 数值在第 1 维
  };
  markPoint?: Record<string, any>;
  markArea?: Record<string, any>;
}

export const realDataChart = ({
  target,
  channels: _channels,
  direction = 'vertical',
  title = '',
  once = false,
  legend: _legend,
}: Opt) => {
  const line = {
    axisLabel: { color: '#fff' },
    splitLine: { show: false },
    axisTick: { show: false },
    axisLine: { show: false },
  };
  let channels = _channels;
  const legend = _legend || [];
  let alphaColors = channels.map((item) =>
    Color(item.color).alpha(0.38).rgb().string(),
  );
  let color = channels.map((item) => item.color);

  const chart = echarts.init(target);
  chart.clear();

  const startTime = Date.now();
  const endTime = startTime + 60000;

  // 生成 Grid 配置
  const genGrid = (idx: number) => {
    if (direction === 'horizontal') {
      return {
        show: true,
        top: '10%',
        left: `${Math.round((100 / channels.length) * idx)}%`,
        width: '32%',
        height: '96%',
        containLabel: true,
      };
    } else {
      return {
        show: true,
        top: `${(100 / channels.length) * idx + 8}%`,
        left: '7%',
        right: '3%',
        height: `${100 / channels.length - 13}%`,
      };
    }
  };
  const showLegend = Object.keys(legend)?.length > 0 ? true : false;
  const opt = {
    animation: false,
    color,
    legend: showLegend ? legend : { show: false },
    tooltip: { trigger: 'axis' },
    axisPointer: { link: [{ xAxisIndex: 'all' }] },
  };

  let xAxis: any[] = [];
  let yAxis: any[] = [];
  let grid: any[] = [];
  let visualMap: any[] = [];
  let series: Series[] = [];
  let startTimes = Array(channels.length).fill(0);
  let lastIdx = Array(channels.length).fill(0);

  const updateChartConfig = (c: Channels[]) => {
    chart.clear();
    channels = c;
    xAxis = [];
    yAxis = [];
    grid = [];
    visualMap = [];
    series = [];
    startTimes = Array(channels.length).fill(0);
    lastIdx = Array(channels.length).fill(0);

    alphaColors = channels.map((item) =>
      Color(item.color).alpha(0.38).rgb().string(),
    );

    color = channels.map((item) => item.color);

    channels.forEach((element, idx) => {
      const _xAxis = {
        ...line,
        id: idx,
        show: false,
        gridIndex: idx,
        type: 'time',
        min: startTime,
        max: endTime,
      };
      const _yAxis = {
        ...line,
        id: idx,
        name: '单位：度(°)',
        gridIndex: idx,
        type: 'value',
        axisLabel: {
          fontSize: 8, // 设置 Y 轴刻度字体大小
        },
        splitLine: {
          lineStyle: {
            color: 'rgba(255, 255, 255, .12)',
            type: 'dashed',
          },
        },
        scale: true,
        nameTextStyle: { color: '#fff', fontSize: 8 },
      };

      const _grid = element.grid || genGrid(idx);
      const _visualMap = {
        show: false,
        dimension: 0,
        seriesIndex: idx,
        pieces: [],
      };

      xAxis.push(_xAxis);
      yAxis.push(_yAxis);
      grid.push(_grid);
      visualMap.push(_visualMap);
      series.push({
        type: 'line',
        name: element.label || element.name,
        showSymbol: false,
        data: [],
        xAxisId: idx,
        yAxisId: idx,
        lineStyle: {
          normal: { width: 1 },
          emphasis: { width: 1 },
        },
        markPoint: {
          symbol: 'pin',
          symbolSize: 30,
          itemStyle: { color: 'rgb(255, 70, 131)' },
          data: [
            {
              name: '最大值',
              type: 'max',
              label: { color: '#fff', fontSize: 8 },
            },
            {
              name: '最小值',
              type: 'min',
              label: { color: '#fff', fontSize: 8 },
            },
          ],
        },
      });
    });
  };

  updateChartConfig(channels);

  let renderChart;
  if (once) {
    renderChart = (dataSource: Data) => {
      channels.forEach((element, idx) => {
        const data = dataSource[element.name];
        if (!data) return;
        xAxis[idx].min = data[0][0];
        xAxis[idx].max = data[data.length - 1][0];
        series[idx].data = data;
      });
      chart.setOption({
        ...opt,
        title: {
          text: title,
          left: 'center',
          top: '2%',
          textStyle: { color: '#fff' },
          show: title !== false,
        },
        xAxis,
        yAxis,
        series,
        grid,
        color,
      });
    };
  } else {
    renderChart = (dataSource: Data, intensity: number = 0) => {
      let delay = 0;
      channels.forEach((element, idx) => {
        const data = dataSource[element.name];
        if (!data) return;
        delay = data[data.length - 1][0] - Date.now();
        if (data[data.length - 1][0] - startTimes[idx] > 60000) {
          startTimes[idx] = data[0][0];
          xAxis[idx].min = startTimes[idx];
          xAxis[idx].max = startTimes[idx] + 60000;
          lastIdx[idx] = data.length;

          const list = series[idx].data.map<[number, number]>((item) => [
            item[0] + 60000,
            item[1],
          ]);
          list.splice(
            0,
            data.length,
            ...data.map((item) => {
              return [item[0], item[1]] as [number, number];
            }),
          );
          series[idx].data = list;
        } else {
          series[idx].data.splice(
            lastIdx[idx],
            data.length,
            ...data.map((item) => {
              return [item[0], item[1]] as [number, number];
            }),
          );
          lastIdx[idx] += data.length;
        }

        const markStart = data[data.length - 1][0];
        series[idx].markArea = {
          itemStyle: { color: channels[idx].color, opacity: 1 },
          data: [[{ xAxis: markStart }, { xAxis: markStart + 1000 }]],
        };

        visualMap[idx].pieces = [
          { lte: markStart, color: channels[idx].color },
          { gt: markStart + 1, color: alphaColors[idx] },
        ];
      });

      chart.setOption({
        ...opt,
        title: {
          text: `${title} | 烈度: ${intensity} | 数据延迟：${delay}ms`,
          left: 'center',
          top: '2%',
          textStyle: { color: '#fff' },
          show: title !== false,
        },
        xAxis,
        yAxis,
        series,
        grid,
        visualMap,
        color,
      });
    };
  }

  window.addEventListener('resize', () => chart.resize());

  return {
    renderChart,
    updateChartConfig,
  };
};

export const getWaveInfo = async (
  devices: any,
  startTime: string,
  endTime: string,
  api: (data) => void,
) => {
  if (!Array.isArray(devices)) devices = [devices];
  const promiseList = devices.map((stationId) => {
    return api({
      stationId: stationId ? stationId.replaceAll('.', '') : '',
      startTime,
      endTime,
    });
  });
  console.log(promiseList, '1');

  const result = await Promise.all(promiseList);
  message.destroy();
  if (result.every((i) => isEmpty(i.data))) {
    message.info('暂无设备触发数据!');
    throw new Error('暂无设备触发数据!');
  }
  const dataInfo = result.reduce((pre, item, index) => {
    pre[devices[index]] = item.data;
    return pre;
  }, {});
  const deviceInfoList = result.map((i, y) => {
    return {
      label: devices[y],
      value: devices[y],
      disabled: !Object.keys(i.data).length,
    };
  });
  return { deviceInfoList, dataInfo };
};

export const getDataInfo = async (
  params: any,
  api: (data) => object,
  error: string,
) => {
  const result = api(params);
  const data = Object.keys(result.data);
  console.log(data, 'data');

  if (!data.length) {
    message.info(error);
    throw new Error(error);
  }
  const dataInfo = result.data;
  const deviceInfoList = data.map((i, y) => {
    return {
      label: i,
      value: i,
      disabled: !Object.keys(result.data[i]).length,
    };
  });
  return { deviceInfoList, dataInfo };
};
